package com.weixun.admin.shiro;

/**
 * Created by myd on 2017/7/17.
 */

import com.jfinal.plugin.activerecord.Record;
import com.weixun.comm.model.vo.Staff;
import com.weixun.admin.model.vo.TreeView;
import com.weixun.admin.service.MenuService;
import com.weixun.admin.service.RoleService;
import com.weixun.admin.service.StaffService;
import com.weixun.model.SysMenu;
import com.weixun.model.SysRole;
import com.weixun.utils.md5.Md5Utils;
import com.weixun.utils.record.RecordUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.ArrayList;
import java.util.List;


public class ShiroDbRealm extends AuthorizingRealm {

    /**
     * 菜单操作类
     */
    static MenuService menuService = new MenuService();

    /**
     * 员工信息操作类
     */
    StaffService staffService = new StaffService();

    /**
     * 角色信息操作类
     */
    RoleService roleService = new RoleService();
    /**
     * 认证回调函数，登录信息和用户验证信息验证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authcToken) throws AuthenticationException {
        System.out.println("##### 身份证认证 #####");
        // 把token转换成User对象
//        Staff userLogin = tokenToUser((UsernamePasswordToken) authcToken);
        UsernamePasswordToken userLogin = (UsernamePasswordToken) authcToken;
        Record record = staffService.find(userLogin.getUsername(),"");
        Staff staff = RecordUtils.converModel(Staff.class,record);
        if(staff != null) {
            //检测密码是否正确交给凭证匹配 --加密方式 salt = username 、hash次数为3、加密算法为md5
            Object principal = authcToken.getPrincipal();
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal,
                    staff.getStaff_password(),this.getName());


            ShiroCache.setLoginUser(staff);


            //预加载角色权限，存入用户缓存
            List<SysRole> roles = roleService.findModelList(staff.getFk_roles_pk());
            ShiroCache.setAttribute(ShiroCache.LOGIN_ROLE,roles);
            //预加载角色资源(菜单)访问权限，存入缓存
            List<SysMenu> permissionAll = new ArrayList<SysMenu>();
            TreeView menu;
            for (SysRole role : roles) {
                menu = new TreeView();
                //按钮
                menu.setType("1");
                List<SysMenu> permissions = menuService.findRolesMenu(menu,role.getRolePk().toString());
                permissionAll.addAll(permissions);
            }
            ShiroCache.setAttribute(ShiroCache.LOGIN_PERMISSION,permissionAll);
            return info;
        }else {
            return null;
        }
    }

    /**
     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("##### 权限认证 #####");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles(ShiroCache.getRoles());
        info.addStringPermissions(ShiroCache.getPermissions());
        return info;
    }

    private Staff tokenToUser(UsernamePasswordToken authcToken) {
        Staff user = new Staff();
        user.setStaff_loginname(authcToken.getUsername());
        //先转换为string
        String password = new String(((char[]) authcToken.getCredentials()));
        //将转换为string的字符串使用md5加密
        user.setStaff_password(Md5Utils.ToMd5(password,1));
        return user;
    }


}

